package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xuecheng.api.content.model.dto.CourseBaseDTO;
import com.xuecheng.api.content.model.qo.QueryCourseModel;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.code.ErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.enums.common.AuditEnum;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.enums.content.CourseChargeEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.content.common.constant.ContentErrorCode;
import com.xuecheng.content.convert.CourseBaseConvert;
import com.xuecheng.content.entity.CourseBase;
import com.xuecheng.content.entity.CourseMarket;
import com.xuecheng.content.mapper.CourseBaseMapper;
import com.xuecheng.content.service.CourseBaseService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.content.service.CourseMarketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 课程基本信息 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class CourseBaseServiceImpl extends ServiceImpl<CourseBaseMapper, CourseBase> implements CourseBaseService {

    @Autowired
    private CourseMarketService courseMarketService;

    /*
     * 1.分页查询
     * 2.条件语句
     * 3.封装返回
     */
    @Override
    public PageVO<CourseBaseDTO> queryCourseBaseList(PageRequestParams params, QueryCourseModel queryCourseModel, Long companyId) {
        //1.效验分页条件
        Long pageNo = params.getPageNo();
        Integer pageSize = params.getPageSize();
        if (ObjectUtils.isEmpty(pageNo) || pageNo > 1)
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        if (ObjectUtils.isEmpty(pageSize) || pageSize > 1)
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);


        //添加条件查询语句
        LambdaQueryWrapper<CourseBase> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.like(!StringUtil.isBlank(queryCourseModel.getCourseName()), CourseBase::getName, queryCourseModel.getCourseName());
        queryWrapper.eq(!ObjectUtils.isEmpty(queryCourseModel.getAuditStatus()), CourseBase::getAuditStatus, queryCourseModel.getAuditStatus());
        queryWrapper.eq(!ObjectUtils.isEmpty(companyId), CourseBase::getCompanyId, companyId);
        //添加分页
        Page<CourseBase> page = new Page<>(pageNo, pageSize);
        //查询
        Page<CourseBase> pageResult = baseMapper.selectPage(page, queryWrapper);

        List<CourseBase> courseBaseList = pageResult.getRecords();

        List<CourseBaseDTO> courseBaseDTOList = Collections.emptyList();
        if (!CollectionUtils.isEmpty(courseBaseList)) {
            courseBaseDTOList = CourseBaseConvert.INSTANCE.entitys2dtos(courseBaseList);
        }
        //设置返回体
        //(List<T> items, long counts, long page, long pageSize)
        PageVO<CourseBaseDTO> pageVO = new PageVO();
        pageVO.setItems(courseBaseDTOList);
        pageVO.setCounts(page.getTotal());
        pageVO.setPage(Integer.valueOf(pageNo + ""));
        pageVO.setPageSize(pageSize);
        return pageVO;
    }

    /*
     * 是否开启事务
     * 判断相关数据
     * companyId charge grade mt name pic st teachmode users
     * 将dto转成po
     * 对新增课程信息添加默认值
     * 判断课程基本信息新增是否成功
     * 判断营销数据是否成功
     * 将保存的数据转成dto并返回
     *
     * @param vo
     * @return
     */
    @Override
    @Transactional
    public CourseBaseDTO createCourseBase(CourseBaseDTO courseBaseDTO, Long companyId) {

        courseBaseVerify(courseBaseDTO, companyId);
        //将dto转成po
        CourseBase courseBase = CourseBaseConvert.INSTANCE.dto2entity(courseBaseDTO);
        courseBase.setCompanyId(companyId);
        courseBase.setAuditStatus(CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode());
        //新增课程基本信息
        boolean saveResult = this.save(courseBase);
        if (!saveResult) {
            throw new RuntimeException("保存课程基本信息失败！");
        }
        //新增课程营销信息
        CourseMarket courseMarket = new CourseMarket();
        courseMarket.setCourseId(courseBase.getId());
        courseMarket.setCharge(courseBaseDTO.getCharge());
        float price = 0f;
        if (courseBaseDTO.getCharge().equals(CourseChargeEnum.CHARGE_YES.getCode())) {
            if (ObjectUtils.isEmpty(courseBaseDTO.getPrice())) {
                throw new RuntimeException("收费价格不能为空");
            }
            price = courseBaseDTO.getPrice().floatValue();
        }
        courseMarket.setPrice(price);
        boolean courseMarketResult = courseMarketService.save(courseMarket);
        if (!courseMarketResult) {
            throw new RuntimeException("课程营销信息保存失败");
        }
        //将数据库最新的信息返回给前端
        CourseBaseDTO dto = CourseBaseConvert.INSTANCE.entity2dto(courseBase);
        dto.setCharge(courseMarket.getCharge());
        dto.setPrice(new BigDecimal(courseMarket.getPrice()));
        return dto;
    }

    private void courseBaseVerify(CourseBaseDTO courseBaseDTO, Long companyId) {
        if (StringUtil.isBlank(courseBaseDTO.getCharge())) {
            throw new RuntimeException("收费规则不能为空");
        }
        if (StringUtil.isBlank(courseBaseDTO.getGrade())) {
            throw new RuntimeException("课程等级不能为空");
        }
        if (StringUtil.isBlank(courseBaseDTO.getMt())) {
            throw new RuntimeException("大分类不能为空");
        }
        if (StringUtil.isBlank(courseBaseDTO.getName())) {
            throw new RuntimeException("课程名称不能为空");
        }
        /*if (StringUtil.isBlank(courseBaseDTO.getPic())) {
            throw new RuntimeException("课程图片不能为空");
        }*/
        if (StringUtil.isBlank(courseBaseDTO.getTeachmode())) {
            throw new RuntimeException("教学模式不能为空");
        }
        if (StringUtil.isBlank(courseBaseDTO.getUsers())) {
            throw new RuntimeException("适用人群不能为空");
        }
        //效验companyId
        if (ObjectUtils.isEmpty(companyId)) {
            throw new RuntimeException(CommonErrorCode.E_403000.getDesc());
        }
    }

    /*
     * 判断 机构id 和 课程id是否为空
     *  判断数据是否被删除
     *  返回数据
     * @param id
     * @param companyId
     * @return
     */
    @Override
    public CourseBaseDTO getCourseBaseById(Long id, Long companyId) {
        CourseBase courseBase = getCourseBaseLogicVerify(id, companyId);
        CourseBaseDTO courseBaseDTO = CourseBaseConvert.INSTANCE.entity2dto(courseBase);
        LambdaQueryWrapper<CourseMarket> courseMarketQuery = Wrappers.lambdaQuery();
        courseMarketQuery.eq(CourseMarket::getCourseId, id);
        //获取课程营销信息
        CourseMarket courseMarket = courseMarketService.getOne(courseMarketQuery);
        if (!ObjectUtils.isEmpty(courseMarket)) {
            courseBaseDTO.setCharge(courseMarket.getCharge());
            if (!ObjectUtils.isEmpty(courseMarket.getPrice()))
                courseBaseDTO.setPrice(new BigDecimal(courseMarket.getPrice().toString()));
        }
        return courseBaseDTO;
    }

    /**
     * 效验核心数据
     * 效验是否被删除
     * 效验审核状态
     * 修改数据
     * 修改营销数据
     *
     * @param dto
     * @param companyId
     * @return
     */
    @Override
    @Transactional
    public CourseBaseDTO modifyCourseBase(CourseBaseDTO dto, Long companyId) {
        //效验课程基本信息
        courseBaseVerify(dto, companyId);
        //效验课程信息是否有效
        CourseBase courseBase = getCourseBaseLogicVerify(dto.getCourseBaseId(), companyId);
        //效验审核状态
        courseAuditStatusVerify(courseBase);

        //修改课程信息
        CourseBase courseBaseInsert = CourseBaseConvert.INSTANCE.dto2entity(dto);
        boolean updateResult = this.updateById(courseBaseInsert);
        if (!updateResult)
            throw new RuntimeException("课程基本信息修改失败");


//        CourseMarket courseMarket = new CourseMarket();
        String charge = dto.getCharge();
        float price = 0;
        if (charge.equals(CourseChargeEnum.CHARGE_YES.getCode())) {
            if (ObjectUtils.isEmpty(dto.getPrice())) {
                throw new RuntimeException("营销价格不能为空");
            } else {
                price = dto.getPrice().floatValue();
            }
        }
//        courseMarket.setCharge(charge);
//        courseMarket.setPrice(price);
//        courseMarket.setCourseId(courseBaseInsert.getId());
        LambdaUpdateWrapper<CourseMarket> courseMarketUpdateWrapper = Wrappers.lambdaUpdate();
        courseMarketUpdateWrapper.set(CourseMarket::getCharge, charge);
        courseMarketUpdateWrapper.set(CourseMarket::getPrice, price);
        courseMarketUpdateWrapper.eq(CourseMarket::getCourseId, courseBaseInsert.getId());
        boolean courseMarketUpdateResult = courseMarketService.update(courseMarketUpdateWrapper);
        if (!courseMarketUpdateResult) {
            throw new RuntimeException("课程营销信息修改失败");
        }
        //将最新的数据返回
        CourseBase cb = this.getById(dto.getCourseBaseId());
        CourseBaseDTO courseBaseDTO = CourseBaseConvert.INSTANCE.entity2dto(cb);
        courseBaseDTO.setPrice(new BigDecimal(price + ""));
        courseBaseDTO.setCharge(charge);
        return courseBaseDTO;
    }

    private void courseAuditStatusVerify(CourseBase courseBase) {
        //判断审核状态 未提交 和审核失败
        String auditStatus = courseBase.getAuditStatus();
        if (!CourseAuditEnum.AUDIT_DISPAST_STATUS.getCode().equals(auditStatus) && !CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode().equals(auditStatus)) {
            throw new RuntimeException(CommonErrorCode.E_403000.getDesc());
        }
    }

    /*  效验是否是本机构下的数据
     * 效验审核状态
     * 删除
     * @param courseBaseId
     * @param companyId
     * @return
     */
    @Override
    public boolean removeCourseBase(Long courseBaseId, Long companyId) {
        //效验删除是否本机构下的数据
        CourseBase courseBase = getCourseBaseLogicVerify(courseBaseId, companyId);
        //效验审核状态是否满足删除条件
        courseAuditStatusVerify(courseBase);
        //删除操作
        boolean removeResult = this.removeById(courseBaseId);
        if (!removeResult) {
            throw new RuntimeException("删除课程信息失败");
        }
        return true;
    }

    /*
     *  效验数据
     *  更新审核状态
     * @param courseBaseId
     * @return
     */
    @Override
    public boolean commitCourseBase(Long courseBaseId, Long companyId) {
        //业务判断
        CourseBase courseBase = getCourseBaseLogicVerify(courseBaseId, companyId);
        //判断审核
        courseAuditStatusVerify(courseBase);
        LambdaUpdateWrapper<CourseBase> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(CourseBase::getId, courseBase.getId());
        updateWrapper.set(CourseBase::getAuditStatus, CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode());

        boolean update = this.update(updateWrapper);
        return update;
    }

    /*
     * 效验课程信息
     *  更新状态
     * @param courseAuditDTO
     * @return
     */
    @Override
    @Transactional
    public boolean approve(CourseBaseDTO courseAuditDTO) {
        //判断关键数据
        String auditStatus = courseAuditDTO.getAuditStatus();
        Long courseBaseId = courseAuditDTO.getCourseBaseId();
        String auditMind = courseAuditDTO.getAuditMind();
        if (ObjectUtils.isEmpty(courseBaseId) || StringUtil.isBlank(auditStatus) || StringUtil.isBlank(auditMind)) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //判断业务数据
        CourseBase courseBase = this.getById(courseBaseId);
        ExceptionCast.cast(ObjectUtils.isEmpty(courseBase),ContentErrorCode.E_120013);
        //判断审核状态
        if (!CourseAuditEnum.AUDIT_DISPAST_STATUS.getCode().equals(auditStatus) && !CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus)) {
            throw new RuntimeException(CommonErrorCode.E_403000.getDesc());
        }
        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseBase::getAuditStatus, auditStatus);
        updateWrapper.set(CourseBase::getAuditMind, auditMind);
        updateWrapper.set(CourseBase::getAuditNums, courseBase.getAuditNums()+1);
        updateWrapper.set(CourseBase::getChangeDate, LocalDateTime.now());
        updateWrapper.eq(CourseBase::getId, courseBase.getId());

        // 4.判断修改的结果
        boolean result = this.update(updateWrapper);
        ExceptionCast.cast(!result,ContentErrorCode.E_120017);
        return false;
    }

    /**
     * 效验课程信息
     *
     * @param id
     * @param companyId
     * @return
     */
    private CourseBase getCourseBaseLogicVerify(Long id, Long companyId) {
        //效验关键数据
        if (ObjectUtils.isEmpty(id) || ObjectUtils.isEmpty(companyId))
            throw new RuntimeException(CommonErrorCode.E_100101.getDesc());
        //查询课程基本信息
        LambdaQueryWrapper<CourseBase> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(CourseBase::getId, id);
        queryWrapper.eq(CourseBase::getCompanyId, companyId);
        CourseBase courseBase = this.getOne(queryWrapper);
        if (ObjectUtils.isEmpty(courseBase))
            throw new RuntimeException(CommonErrorCode.E_100104.getDesc());
        //判断是否被删除
        Integer status = courseBase.getStatus();
        if (ObjectUtils.nullSafeEquals(status, CommonEnum.DELETE_FLAG.getCodeInt()))
            throw new RuntimeException("课程基础信息已删除");
        return courseBase;
    }
}
